﻿package com.saint.elasticity 
{
	import com.saint.utils.Logger;
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Point;
	import flash.text.TextField;
	/**
	 * ...
	 * @author kembera
	 */
	public class ElasticObject extends Sprite implements IAnchorPoint
	{
				
		private	var elasticProperties:ElasticProps ;
		private var anchorPoints:Array = new Array();
		private var drawSprings:Boolean = true;
		private var bg:Sprite = new Sprite();
		private var dragActive:Boolean;
		private var _showSpring:Boolean = false;
		private var _strength:Number = 0.1;	
		private var mousePoint:IAnchorPoint;
		
		private var mouseStrength:Number = 0.5; // 0.1 weak
		
		private var buttonSize:Number = 50;
		
									
		private var xMove:Number = 0;
		private var yMove:Number = 0;
		
		
		public var type:String = "EO";
		
		/**
		 * constructor
		 */
		public function ElasticObject()
		{
			Logger.info("ElasticObject.ElasticObject");
			
			buttonMode = true;
			
			/* get the elastic properties for the object */
			elasticProperties = new ElasticProps();
			
			/** draw graphics */
			drawSquare();
			addChild(bg);
		}
		
		public function label(val:String):void
		{
			var txt:TextField = new TextField();
			txt.text = val;
			addChild(txt);
		}
		
		/**
		 * gets a spring from another IAnchorPoint
		 * 
		 * @param	pnt
		 */
		public function attachSpringFrom(obj:IAnchorPoint):void
		{
			Logger.info("ElasticObject.setAnchorPoint " + obj.x + ", " + obj.y);			
			anchorPoints.push(obj);		
		}
		
		/**
		 * sets listeners and starts, creates the mouse anchor point and starts enterFrame event listener
		 */
		public function init():void
		{
			Logger.info("ElasticObject.init " + stage);						
			//addEventListener(Event.ENTER_FRAME, enterFrameEvents);
			addEventListener(MouseEvent.MOUSE_DOWN, onMouseDownHandler);
			addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);
			stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUpHandler);	
			mousePoint = new FixedAnchorPoint(0, 0, false, mouseStrength);		
		}
		
		private function onMouseUpHandler(e:MouseEvent):void 
		{
			dragActive = false;
		}
		
		private function onMouseDownHandler(e:MouseEvent):void 
		{
			Logger.debug("ElasticObject.onMouseDownHandler parent.mouseX: " + parent.mouseX)
			Logger.debug("ElasticObject.onMouseDownHandler stage.mouseX: " + stage.mouseX)
			dragActive = true;
		}
		
		
		private function drawSquare():void
		{	bg.graphics.moveTo(0, 0);
			bg.graphics.beginFill(0xffcc00, 0.5);
			bg.graphics.drawRect(buttonSize*(-0.5), buttonSize*(-0.5), buttonSize, buttonSize);
			bg.graphics.endFill();
		}
		
		
		private function drawSpring(pnt:Object):void
		{
			bg.graphics.lineStyle(1, 0x000000, 0.5);
			bg.graphics.moveTo(pnt.x- x, pnt.y - y) ;
			bg.graphics.lineTo(0, 0);
		}
		
		/**
		 * 	ENTER FRAME HANDLER
		 * 
		 *  loops through attached anchor points and asserts their influence
		 * 	
		 * 
		 * 
		 * 
		 * @param	e
		 */
		public function enterFrameEvents(e:Event):void 
		{
			Logger.debug("ElasticObject.enterFrameEvents Start: " + this.name)
			bg.graphics.clear();
			
			for (var i:Number = 0; i < anchorPoints.length; i++)
			{				
				assertAnchorInfluence(anchorPoints[i]);			
			}
			
			/* make the mouse have an influence if a the point is being dragged */
			if (dragActive)
			{
				mousePoint.x = parent.mouseX;
				mousePoint.y = parent.mouseY;				
				assertAnchorInfluence(mousePoint);
			}
			
			/* show the spring */
			if (drawSprings)
			{
				for (var n:Number = 0; n < anchorPoints.length; n++)
				{
					if (IAnchorPoint(anchorPoints[n]).getShowSpring())
					{					
						drawSpring(anchorPoints[n]);
					}
				}
			}
			
			drawSquare();
			Logger.debug("ElasticObject.enterFrameEvents End: " + this.name + ", this.y: " + this.y + ", this.x: " + this.x)
			
		}

		
		/**
		 * 
		 * @param	pnt
		 */
		private function assertAnchorInfluence(pnt:IAnchorPoint):void 
		{
			var ydist:Number = pnt.y - this.y;
			var xdist:Number = pnt.x - this.x;	
			
			xMove = elasticProperties.calculateXMov(xdist,pnt.strength);
			yMove = elasticProperties.calculateYMov(ydist, pnt.strength);	
			
			this.y += yMove;
			this.x += xMove;
		}
		
		
		/**
		 * GETTERS AND SETTERS
		 * 
		 */
		public function getShowSpring():Boolean { return _showSpring; }
		public function setShowSpring(val:Boolean)
		{
			_showSpring = val;
		}
		
		public function get strength():Number { return _strength; }		
		public function set strength(value:Number):void 
		{
			_strength = value;
		}
	}

}